package cn.rkylin.oms.warehouse.local.localStockIn.service;

import cn.rkylin.apollo.common.util.SnoGerUtil;
import cn.rkylin.core.service.ApolloService;
import cn.rkylin.oms.common.consts.StockInStatus;
import cn.rkylin.oms.common.consts.YesNoConst;
import cn.rkylin.oms.goods.dao.IGoodsDAO;
import cn.rkylin.oms.goods.vo.GoodsSkuVO;
import cn.rkylin.oms.goodscost.dao.IGoodsCostDAO;
import cn.rkylin.oms.goodscost.vo.GoodsCostVO;
import cn.rkylin.oms.warehouse.stock.dao.IStockDAO;
import cn.rkylin.oms.warehouse.stock.service.IStockService;
import cn.rkylin.oms.warehouse.stock.vo.StockVO;
import cn.rkylin.oms.warehouse.stockin.dao.StockInDAOImpl;
import cn.rkylin.oms.warehouse.stockin.dao.StockInGoodsDAOImpl;
import cn.rkylin.oms.warehouse.stockin.domain.StockIn;
import cn.rkylin.oms.warehouse.stockin.domain.StockInGoods;
import cn.rkylin.oms.warehouse.stockin.domain.StockinType;
import cn.rkylin.oms.warehouse.stockin.vo.StockInGoodsVO;
import cn.rkylin.oms.warehouse.stockin.vo.StockInVO;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 入库Service
 *
 * @author 齐涛
 * @version 1.0
 * @created 11-9-2017 10:51:30
 */
@Repository(value = "localStockInService")
public class LocalStockInServiceImpl extends ApolloService implements ILocalStockInService {

    @Autowired
    private StockInDAOImpl stockInDAOImpl;

    @Autowired
    private StockInGoodsDAOImpl stockInGoodsDAOImpl;

    @Autowired
    private IStockService stockService;

    @Autowired
    private IStockDAO stockDAO;

    @Autowired
    private IGoodsCostDAO goodsCostDAO;

    @Autowired
    private IGoodsDAO goodsDAO;

    /**
     * 查询入库单列表
     *
     * @param page      页号
     * @param rows      页大小
     * @param stockInVO 入库单VO
     * @return 入库单列表
     * @throws Exception 异常
     */
    @SuppressWarnings("rawtypes")
    public PageInfo findByWhere(int page, int rows, StockInVO stockInVO) throws Exception {
        PageInfo<StockInVO> rdfundReasonTypeVOList = findPage(page, rows, "pageSelectStockIn", stockInVO);
        return rdfundReasonTypeVOList;
    }

    public PageInfo findByWhereLocal(int page, int rows, StockInVO stockInVO) throws Exception {
        PageInfo<StockInVO> rdfundReasonTypeVOList = findPage(page, rows, "pageSelectStockInLocal", stockInVO);
        return rdfundReasonTypeVOList;
    }

    /**
     * 查询入库单商品列表
     *
     * @param stockInGoodsVO 入库单商品VO
     * @return 入库单信息
     * @throws Exception 异常
     */
    public List<StockInGoodsVO> selectStockInGoodsList(StockInGoodsVO stockInGoodsVO) throws Exception {
        return stockInGoodsDAOImpl.selectStockInGoodsList(stockInGoodsVO);
    }

    /**
     * 查询入库单信息
     *
     * @param stockInVO 入库单VO
     * @return 入库单信息
     * @throws Exception 异常
     */
    public StockInVO getStockInInfo(StockInVO stockInVO) throws Exception {
        StockInVO data = stockInDAOImpl.getStockInInfo(stockInVO);

        StockInGoodsVO stockInGoodsVO = new StockInGoodsVO();
        stockInGoodsVO.setStockinId(stockInVO.getStockinId());
        stockInGoodsVO.setOrderBy("goods_code, sku_code");
        List<StockInGoodsVO> goodsDataList = stockInGoodsDAOImpl.selectStockInGoodsList(stockInGoodsVO);
        data.setStockInGoodsVOList(goodsDataList);

        return data;
    }

    /**
     * 审核入库单状态
     *
     * @param stockinId 入库单Id
     * @throws Exception 异常
     */
    public void saveAuditStockIn(String stockinId) throws Exception {
        // 审核入库单
        StockIn stockIn = new StockIn();
        stockIn.setStockinId(stockinId);
        stockIn.setApprTime(new Date());
        stockIn.setStockinStatus("f");
        stockInDAOImpl.updateStockIn(stockIn);

        // 更新库存在途数
        this.updateOnwayQty(stockinId, 1);
    }

    /**
     * 删除入库单
     *
     * @param stockinId     入库单Id
     * @param stockInStatus 入库单状态
     * @throws Exception 异常
     */
    public void deleteStockIn(String stockinId, String stockInStatus) throws Exception {
        // 删除入库单
        StockIn stockIn = new StockIn();
        stockIn.setStockinId(stockinId);
        stockInDAOImpl.deleteStockIn(stockIn);

        // 待入库删除后更新库存在途数
        if (StockInStatus.WAIT_STOCKIN.equals(stockInStatus)) {
            this.updateOnwayQty(stockinId, -1);
        }
    }

    /**
     * 更新在途数
     *
     * @param stockinId 入库单Id
     * @throws Exception 异常
     */
    private void updateOnwayQty(String stockinId, int onwayQtyCoefficient) throws Exception {
        // 得到入库单信息
        StockInVO stockInVO = new StockInVO();
        stockInVO.setStockinId(stockinId);
        StockInVO stockInInfo = stockInDAOImpl.getStockInInfoForUpdateOnwayQty(stockInVO);
        // 得到入库单SKU信息
        StockInGoodsVO stockInGoodsVO = new StockInGoodsVO();
        stockInGoodsVO.setStockinId(stockinId);
        List<StockInGoodsVO> stockInGoodsInfoList = stockInGoodsDAOImpl.selectStockInGoodsList(stockInGoodsVO);

        // 更新库存在途数
        for (StockInGoodsVO stockInGoodsInfo : stockInGoodsInfoList) {
            StockVO stockVO = new StockVO();
            stockVO.setEntId(stockInInfo.getEntId());
            stockVO.setSkuId(stockInGoodsInfo.getSkuId());
            stockVO.setStorId(stockInInfo.getStorId());
            stockVO.setSourceCode(stockInInfo.getStockinCode());
            stockVO.setTag("菜鸟入库单审核");
            stockVO.setOnwayQty(stockInGoodsInfo.getQty() * onwayQtyCoefficient);
            stockService.updateStock(stockVO);
        }
    }

    /**
     * 添加入库单
     *
     * @param stockInVO 入库单VO
     * @return 插入入库单条数
     * @throws Exception 异常
     */
    public int insertStockIn(StockInVO stockInVO) throws Exception {
        // 添加入库单
        StockIn stockIn = new StockIn();
        BeanUtils.copyProperties(stockInVO, stockIn);
        int insertCount = stockInDAOImpl.insertStockIn(stockIn);

        // 添加入库单商品
        List<StockInGoodsVO> list = stockInVO.getStockInGoodsVOList();
        for (int i = 0; i < list.size(); i++) {
            StockInGoodsVO stockInGoodsVO = list.get(i);
            StockInGoods stockInGoods = new StockInGoods();
            BeanUtils.copyProperties(stockInGoodsVO, stockInGoods);

            GoodsSkuVO goodsSkuVO = new GoodsSkuVO();
            goodsSkuVO.setSkuCode(list.get(i).getSkuCode());
            goodsSkuVO.setPrjId(stockInVO.getPrjId());
            List<GoodsSkuVO> goodsSkuVOList = findPage("selectGoodsSkuListBySkuCode", goodsSkuVO);
            stockInGoods.setGoodsSkuCost(goodsSkuVOList.get(0).getCostPrice());
            stockInGoodsDAOImpl.insertStockInGoods(stockInGoods);
        }

        return insertCount;
    }

    /**
     * 修改入库单(备注)
     *
     * @param stockInVO 入库单VO
     * @return 修改入库单备注条数
     * @throws Exception 异常
     */
    public int updateStockInRemark(StockInVO stockInVO) throws Exception {
        StockIn stockIn = new StockIn();
        BeanUtils.copyProperties(stockInVO, stockIn);
        int updateCount = stockInDAOImpl.updateStockIn(stockIn);

        return updateCount;
    }

    /**
     * 修改入库单
     *
     * @param stockInVO 入库单VO
     * @return 修改入库单条数
     * @throws Exception 异常
     */
    public int updateStockIn(StockInVO stockInVO) throws Exception {
        // 修改入库单
        StockIn stockIn = new StockIn();
        BeanUtils.copyProperties(stockInVO, stockIn);
        int updateCount = stockInDAOImpl.updateStockIn(stockIn);

        // 逻辑删除该入库单对应的商品
        StockInGoods stockInGoods = new StockInGoods();
        stockInGoods.setStockinId(stockInVO.getStockinId());
        stockInGoods.setDeleted(YesNoConst.YES);
        stockInGoodsDAOImpl.updateStockInGoods(stockInGoods);

        // 修改入库单商品
        List<StockInGoodsVO> list = stockInVO.getStockInGoodsVOList();
        for (int i = 0; i < list.size(); i++) {
            StockInGoodsVO stockInGoodsVO = list.get(i);
            StockInGoods goodsBean = new StockInGoods();
            BeanUtils.copyProperties(stockInGoodsVO, goodsBean);
            goodsBean.setDeleted(YesNoConst.NO);

            GoodsSkuVO goodsSkuVO = new GoodsSkuVO();
            goodsSkuVO.setSkuCode(list.get(i).getSkuCode());
            goodsSkuVO.setPrjId(stockInVO.getPrjId());
            List<GoodsSkuVO> goodsSkuVOList = findPage("selectGoodsSkuListBySkuCode", goodsSkuVO);
            goodsBean.setGoodsSkuCost(goodsSkuVOList.get(0).getCostPrice());

            int result = stockInGoodsDAOImpl.updateStockInGoods(goodsBean);
            if (result == 0) {
                stockInGoodsDAOImpl.insertStockInGoods(goodsBean);
            }
        }

        return updateCount;
    }

    /**
     * 查询入库类型列表
     * @return
     * @throws Exception
     */
    public List<StockinType> selectStockinTypeList() throws Exception {
        return stockInDAOImpl.selectStockinTypeList();
    }

    @Override
    public int getUnGoingCount(Map<String, String> paramMap) throws Exception {
        return stockInDAOImpl.getUnGoingCount(paramMap);
    }

    @Override
    public String updateFinshStockIn(String id,String account,String prjId) throws Exception {
        //更新状态
        StockIn stockIn = new StockIn();
        stockIn.setStockinId(id);
        stockIn.setStockinStatus("z");
        stockIn.setFactInTime(new Date());
        stockIn.setUpdateTime(new Date());
        stockInDAOImpl.updateStockIn(stockIn);

        StockInVO stockInVO = new StockInVO();
        stockInVO.setStockinId(id);
        StockInVO data = getStockInInfo(stockInVO);
        //更新库存
        StockInGoodsVO stockInGoodsVO = new StockInGoodsVO();
        stockInGoodsVO.setStockinId(id);
        List<StockInGoodsVO> listStockInSku = stockInGoodsDAOImpl.selectStockInGoodsList(stockInGoodsVO);
        if (listStockInSku!=null && listStockInSku.size()>0){
            for (int i = 0 ; i < listStockInSku.size() ; i++){

                listStockInSku.get(i).setKind("real");

                GoodsSkuVO goodsSkuVO = new GoodsSkuVO();
                goodsSkuVO.setSkuCode(listStockInSku.get(i).getSkuCode());
                goodsSkuVO.setPrjId(prjId);
                List<GoodsSkuVO> goodsSkuVOList = findPage("selectGoodsSkuListBySkuCode", goodsSkuVO);
                listStockInSku.get(i).setGoodsSkuCost(goodsSkuVOList.get(0).getCostPrice());


                stockInGoodsDAOImpl.updateStockInGoods(listStockInSku.get(i));

                StockVO skuStockUpdate = new StockVO();
                skuStockUpdate.setEntId(data.getEntId());
                skuStockUpdate.setStorId(data.getStorId());
                skuStockUpdate.setSkuId(listStockInSku.get(i).getSkuId());
                skuStockUpdate.setSourceCode(data.getStockinCode());
                skuStockUpdate.setTag("本地入库单");
                int junkQty = 0;
                int stockQty = 0;
                if ("zp".equals(listStockInSku.get(i).getInventoryType())){
                    stockQty=stockQty+ listStockInSku.get(i).getQty();
                } else {
                    junkQty=junkQty+listStockInSku.get(i).getQty();
                }
                skuStockUpdate.setJunkQty(junkQty);
                skuStockUpdate.setStockQty(stockQty);
                int iStockRes = stockService.updateStock(skuStockUpdate);
                if (iStockRes <= 0) {
                    return "失败";
                }

                //加权计算
                GoodsCostVO goodsCostTemp = new GoodsCostVO();
                goodsCostTemp.setSkuId(listStockInSku.get(i).getSkuId()); //skuid
                goodsCostTemp.setQty(junkQty+stockQty); //实际入库数量
                goodsCostTemp.setSourceId(data.getStockinId()); //来源单据ID
                goodsCostTemp.setSourceCode(data.getStockinCode()); //来源单据编码
                goodsCostTemp.setEntId(data.getEntId()); //企业ID
                goodsCostTemp.setOperType("本地入库单"); //操作类型
                goodsCostTemp.setRemark("本地入库单");
                goodsCostTemp.setOrigCost(listStockInSku.get(i).getGoodsSkuCost());

                //调用 移动加权成本价计算 函数，实现系统规格商品成本价加权计算
                Map<String,Object> res = DoGoodsCostComputer(goodsCostTemp,account);
            }
        }



        return "成功";
    }

    @Override
    public String delStockIn(String id, String account) throws Exception {
        //更新状态
        StockIn stockIn = new StockIn();
        stockIn.setStockinId(id);
        stockIn.setDeleted("y");
        stockIn.setUpdateTime(new Date());
        stockInDAOImpl.updateStockIn(stockIn);
        return "成功";
    }

    /**
     * 商品成本移动加权计算 wangxing add
     * 公式：( (期初库存 * 即时成本价)  +  (当前单据实际入库数 * 单据成本价 或 采购单价)  )  /  (期初库存 + 当前单据实际入库数)
     *
     * @param parmGoodsCost
     * @return
     * @throws Exception
     */
    public Map<String,Object> DoGoodsCostComputer(GoodsCostVO parmGoodsCost,String account) throws Exception {
        Map<String,Object> res = new HashMap<String,Object>() ;
        int iRes = 0;
        //期初库存数
        int iBeginStockQty = 0;
        //期初成本价
        BigDecimal bdBeginCost = BigDecimal.ZERO;
        //当前单据成本价
        BigDecimal bdNowCost = BigDecimal.ZERO;
        //计算后的成本价
        BigDecimal bdLastCost = BigDecimal.ZERO;

        //获取当前系统规格库存数相关信息
        StockVO skuStockVO = new StockVO();
        skuStockVO.setSkuId(parmGoodsCost.getSkuId());
        skuStockVO.setEntId(parmGoodsCost.getEntId());
        StockVO skuStockVORes = stockDAO.selectSkuStockBySkuId(skuStockVO);

        if (skuStockVORes != null) {
//1、计算移动加权成本价-------------------------------------------------------------------------------------
            //商品即时成本价
            BigDecimal bdGoodsSkuCost = skuStockVORes.getGoodsSkuCost();
            //总库存数加上实际入库数大于0
            if ((skuStockVORes.getStockQty() + skuStockVORes.getJunkQty()) > 0) {
                //如果 即时成本价为0，则当前移动加权成本价为当前单据上的成本价 或 采购单价
                if (bdGoodsSkuCost == BigDecimal.ZERO) {
                    bdLastCost = parmGoodsCost.getOrigCost();
                } else {
                    //当前商品即时成本价非0，计算成移动加权成本价

                    //期初库存数
                    iBeginStockQty = skuStockVORes.getStockQty() + skuStockVORes.getJunkQty() - parmGoodsCost.getQty();
                    //期初成本价 = 期初库存数 * 即时成本价
                    bdBeginCost = bdGoodsSkuCost.multiply(BigDecimal.valueOf(iBeginStockQty));
                    //当前单据成本价 = 实际入库数 * 单据成本价(或采购单价)
                    bdNowCost = parmGoodsCost.getOrigCost().multiply(BigDecimal.valueOf(parmGoodsCost.getQty()));
                    //计算后成本价 = (期初成本价 + 当前单据成本价)  /  (期初库存数 + 实际入库数)
                    bdLastCost = bdNowCost.add(bdBeginCost);
                    bdLastCost = bdLastCost.divide(BigDecimal.valueOf(skuStockVORes.getStockQty() + skuStockVORes.getJunkQty()), 2, BigDecimal.ROUND_HALF_UP);
                }
            } else {
                //总库存数加上实际入库数小于等于0，加权平均值取商品规格原成本
                bdLastCost = bdGoodsSkuCost;
            }
//2、将结果插入到商品成本管理表中 oms_goods_cost------------------------------------------------------------
            GoodsCostVO goodsCost = new GoodsCostVO();
            goodsCost.setGoodsCostId(SnoGerUtil.getUUID());
            goodsCost.setEntId(skuStockVORes.getEntId());
            goodsCost.setSkuId(skuStockVORes.getSkuId());
            goodsCost.setSkuCode(skuStockVORes.getSkuCode());
            goodsCost.setSkuName(skuStockVORes.getSkuName());
            goodsCost.setGoodsId(skuStockVORes.getGoodsId());
            goodsCost.setGoodsCode(skuStockVORes.getGoodsCode());
            goodsCost.setGoodsName(skuStockVORes.getGoodsName());
            goodsCost.setOrigCost(bdGoodsSkuCost);
            goodsCost.setCurtCost(bdLastCost);
            goodsCost.setOperTime(new Date());
            goodsCost.setOperType(parmGoodsCost.getOperType());
            goodsCost.setOperMode("手动");
            goodsCost.setOperUserName(account);
            goodsCost.setSourceId(parmGoodsCost.getSourceId());
            goodsCost.setSourceCode(parmGoodsCost.getSourceCode());
            //总库存数加上实际入库数大于0
            if ((skuStockVORes.getStockQty() + skuStockVORes.getJunkQty()) > 0) {
                String strFormula = "(" + String.valueOf(iBeginStockQty) + "*" + String.valueOf(bdGoodsSkuCost)
                        + "+" + String.valueOf(parmGoodsCost.getQty()) + "*" + String.valueOf(parmGoodsCost.getOrigCost())
                        + ")/(" + String.valueOf(iBeginStockQty) + "+" + String.valueOf(parmGoodsCost.getQty()) + ")";
                goodsCost.setRemark(strFormula);
            } else {
                goodsCost.setRemark(parmGoodsCost.getRemark());
            }
            int iInsert = goodsCostDAO.insertGoodsCostChanger(goodsCost);
            if (iInsert > 0) {
//3、更新系统规格成本价为当前计算结果-----------------------------------------------------------------------
                GoodsSkuVO sysGoodsSku = new GoodsSkuVO();
                sysGoodsSku.setSkuId(skuStockVORes.getSkuId());
                sysGoodsSku.setCostPrice(bdLastCost);
                sysGoodsSku.setUpdateTime(new Date());
                int iUpdate = goodsDAO.updateGoodsSkuCostBySkuId(sysGoodsSku);
            }
            iRes = iInsert;
        }
        res.put("iRes",iRes);
        res.put("bdLastCost",bdLastCost);
        return res;
    }

}
